﻿/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://git.oschina.net/cblock/embedme
 * Copyright 2014~2017 @ ShenZhen ,China
*******************************************************************************/
#include "Tracer.h"
#include "Semaphore.h"
#ifdef OS_CYGWIN
#else
Semaphore::Semaphore()
{
}

Semaphore::~Semaphore()
{
}
/**
 *  \brief  等待信号量
 *  \param  void
 *  \return 成功返回true,失败返回false
 *  \note   使信号量值减1,如果无资源可申请,则阻塞.
 */
bool Semaphore::wait()
{
    if (0==sem_wait(&m_sem))
    {
        return true;
    }
    return false;
}
/**
 *  \brief  尝试等待信号量
 *  \param  void
 *  \return 成功返回true,失败返回false
 *  \note   使信号量值减1,如果无资源可申请,则返回.
 */
bool Semaphore::tryWait()
{
    if (0==sem_trywait(&m_sem))
    {
        return true;
    }
    return false;
}
/**
 *  \brief  释放信号量
 *  \param  void
 *  \return 成功返回true,失败返回false
 *  \note   使信号量值增加1,释放资源
 */
bool Semaphore::post()
{
    if (0==sem_post(&m_sem))
    {
        return true;
    }
    return false;
}
/**
 *  \brief  获取信号量值
 *  \param  value 当前值
 *  \return 成功返回true,失败返回false
 *  \note   当value>0说明有资源,=0无资源,<0表示有|value|个线程在等待资源
 */
bool Semaphore::getValue(int& value)
{
    if (-1==sem_getvalue(&m_sem,&value))
    {
        return false;
    }
    return true;
}

NSemaphore::NSemaphore(char * name):
m_name(name)
{
}
NSemaphore::~NSemaphore()
{
    /* 从文件系统中删除信号量 */
    if (-1==sem_unlink(m_name.c_str()))
    {
        TRACE_ERR_CLASS("sem unlink error:%s\n",ERROR_STRING);
    }
}
/**
 *  \brief  打开有名信号量
 *  \param  void
 *  \return 成功返回true,失败返回false
 *  \note   信号量存在,则返回,不存在则创建,创建成功生成/tmp/sem.name
 */
bool NSemaphore::open(int value)
{
    sem_t* sem = sem_open(m_name.c_str(),O_EXCL);
    if (sem==SEM_FAILED)
    {  
        sem = sem_open(m_name.c_str(),O_CREAT,0644,value);
        if (sem==SEM_FAILED)
        {
            TRACE_ERR_CLASS("sem create error:%s\n",ERROR_STRING);
            return false;
        }
    }
    m_sem = *sem;
    return true;
}
/**
 *  \brief  关闭有名信号量
 *  \param  void
 *  \return 成功返回true,失败返回false
 *  \note   当信号量不再使用时,请关闭.进程退出时也会自动关闭,
 *          但关闭信号量不会真正删除信号量,删除需要使用sem_unlink.
 */
bool NSemaphore::close()
{
    if (-1==sem_close(&m_sem))
    {
        TRACE_ERR_CLASS("sem close error:%s\n",ERROR_STRING);
        return false;
    }
    return true;
}

UNSemaphore::UNSemaphore()
{
}
UNSemaphore::~UNSemaphore()
{
}
/**
 *  \brief  打开无名信号量
 *  \param  void
 *  \return 成功返回true,失败返回false
 *  \note   none
 */
bool UNSemaphore::open(int value)
{
    if (-1==sem_init(&m_sem, 0, value))
    {
        TRACE_ERR_CLASS("sem init error:%s\n",ERROR_STRING);
        return false;
    }
    return true;
}
/**
 *  \brief  关闭无名信号量
 *  \param  void
 *  \return 成功返回true,失败返回false
 *  \note   none
 */
bool UNSemaphore::close()
{
    if (-1==sem_destroy(&m_sem))
    {
        TRACE_ERR_CLASS("sem destroy error:%s\n",ERROR_STRING);
        return false;
    }
    return true;
}
#endif